/******************************************************************************
**
** COBJFile.h
**
** Purpose: To read in 3D models described in the OBJ file format and store 
** them in memory for use by a 3D engine.
**
** Modification History:
**		11/13/00 created by VenTure
**
** Copyright: (c) 2000 Justin S. Houk, jhouk@mailcity.com.  Permission to use 
** and modify freely given so long as this original copyright notice remains 
** unchanged.
**
******************************************************************************/

#ifndef _COBJFILE_H_
#define _COBJFILE_H_

#ifndef NULL
#define NULL 0
#endif

// Keep the stoopid M$ STL from spewing chunks because their variable names are
// too big for debugging
#pragma warning(disable:4786)

#include <map>
#include <vector>
#include <string>

#include "cmodelfile.h"

using namespace std;

struct ArrayIndex
{
	int vertexIndex;
	int vertexTextureIndex;
	int vertexNormalIndex;
};

typedef vector < ArrayIndex > ListArrayIndex;

struct Face
{
	ListArrayIndex arrayIndices;
};

typedef vector<Face> ListFace;

struct SmoothingGroup
{
	int id;

	ListFace faces;
};

typedef map<int, SmoothingGroup, less<int> > MapInt2SmoothingGroup;

struct Group
{
	string name;
	int numFaces;

	MapInt2SmoothingGroup smoothingGroups;
	int curSmoothingGroupKey;
};

typedef map<string, Group, less<string> > MapString2Group;
typedef map<string, Group*, less<string> > MapString2GroupPtr;

enum {MAX_VERTEX = 8192000}; // enum-as-const-for-array-size-hack

class COBJFile : public CModelFile
{
public:
	COBJFile(const char* filename);

	const char* GetName() const 
	{ return _name.c_str(); }

	bool Load();

	int GetNumMeshPoints() const
	{ return _curVertex; }

	const Vertex* GetMeshVertex(int i) const
	{ return &_vertices[i]; }

	int GetNumFaces();

	bool HasTextureCoords() const
	{ return (_curVertexTexture > 0); }

	int GetNumVertsPerFace()
	{ return _groups.begin()->second.smoothingGroups.begin()->second.faces.begin()->arrayIndices.size(); }

	int GetFaceVertexIndex(int face, int vertex);
	int GetFaceTextureVertexIndex(int face, int vertex);
	int GetFaceNormalVertexIndex(int face, int vertex);

	const Vertex* GetFaceVertex(int face, int vertex);
	const VertexTexture* GetFaceTextureVertex(int face, int vertex);
	const VertexNormal* GetFaceNormalVertex(int face, int vertex);
	
protected:
	void _SetupDefaultGroup();
	void _SetupSmoothingGroup(const MapString2GroupPtr::iterator&, int);
	void _SetupFace(string, Face*);
	SmoothingGroup* _AlignGroups(int*);

protected:
	string _fileName;
	string _name;

	Vertex			_vertices[MAX_VERTEX];
	VertexTexture	_vertexTextures[MAX_VERTEX];
	VertexNormal	_vertexNormals[MAX_VERTEX];

	int _curVertex;
	int _curVertexTexture;
	int _curVertexNormal;

	MapString2Group _groups;
	MapString2GroupPtr _curGroups;
};

#endif